package de.bazinga.rotw.hud;

import java.util.Iterator;
import java.util.Stack;
import java.util.Vector;

import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.BlendState;
import com.jmex.game.state.GameStateManager;

import de.bazinga.rotw.base.Flag;
import de.bazinga.rotw.base.attacker.AttackerList;
import de.bazinga.rotw.base.attacker.BaseAttacker;
import de.bazinga.rotw.game.Game;
import de.bazinga.rotw.game.RotwGameState;
import de.bazinga.rotw.gameModes.CaptureTheZombie;
import de.bazinga.rotw.gameModes.DefendYourBase;
import de.bazinga.rotw.person.OpponentList;
import de.bazinga.rotw.person.Person;
import de.bazinga.rotw.texture.TextureCache;

public class GameHUD extends Node {
	private static final long serialVersionUID = 1L;

	private Quad icon = null;
	
	private Quad zombie = null;
	
	private Quad radar = null;

	private BlendState bs = null;
	
	private Vector<Quad> radarQuads = new Vector<Quad>();
	private Stack<Quad> unusedRadarQuads = new Stack<Quad>();
	Quaternion cameraDir = new Quaternion();
	/*private TextureState radarTexture;
	private Texture texture;
	private long lastUpdate = 0;*/
	
	public GameHUD() {
		super("GameHUD");
		
		
		/**
		 * Create BlendState
		 */
		bs = Game.getGame().getDisplay().getRenderer().createBlendState();
		bs.setBlendEnabled(true);
		bs.setSourceFunction(BlendState.SourceFunction.SourceAlpha);
		bs.setDestinationFunction(BlendState.DestinationFunction.OneMinusSourceAlpha);
		bs.setTestEnabled(true);
		bs.setTestFunction(BlendState.TestFunction.GreaterThan);
		
		
		
		/**
		 * QUAD
		 */
		Quad hudQuad = createHUDQuad("hud", "aimcross.png", 40, 40,
				new Vector3f(
						Game.getGame().getDisplay().getWidth()/2,
						Game.getGame().getDisplay().getHeight()/2,
						1));
		this.attachChild(hudQuad);	
		
		
		
		
		
		Quad dataBg = createHUDQuad("hud", "hud/dataBg.png", 236, 125, new Vector3f(118,65,1));
		this.attachChild(dataBg);
		
		
		
		
		icon = createHUDQuad("hud", "hud/tux.png", 64, 64, 
				new Vector3f(
						Game.getGame().getDisplay().getWidth()-64,
						64,
						1));
		this.attachChild(icon);
		
		
		
		/**
		 * RADAR
		 */
		radar = createHUDQuad("hud", "texture/radar.png", 128, 128, 
					new Vector3f(
						Game.getGame().getDisplay().getWidth()-64,
						Game.getGame().getDisplay().getHeight()-64,
						1));	
		this.attachChild(radar);
		
		

		zombie = createHUDQuad("zombie", "hud/zombie.png", 64, 64, 
				new Vector3f(
						Game.getGame().getDisplay().getWidth()-64,
						130,
						1));
		zombie.setCullHint(CullHint.Always);
		this.attachChild(zombie);
		
	}
	
	
	/**
	 * Creates a Quad on the HUD with the given texture and a Blendstate
	 * @param name the name of the quad
	 * @param texture the texture of the quad
	 * @param location the location
	 * @return
	 */
	public Quad createHUDQuad(String name, String texture, float width, float height, Vector3f location) {
		Quad quad = new Quad(name, width, height);
		quad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
		
		quad.setLocalTranslation(location);
		
		quad.setRenderState(TextureCache.getInstance().getTexture(texture));
		
		quad.setRenderState(bs);
		
		quad.setLightCombineMode(Spatial.LightCombineMode.Off);
		quad.updateRenderState();
		
		return quad;
	}
	
	
	
	public void setWeaponIcon(String tex) {
		icon.setRenderState(TextureCache.getInstance().getTexture("hud/"+tex));
		
		icon.updateRenderState();	
	}
	
	
	public void showZombie() {
		zombie.setCullHint(CullHint.Never);
	}
	
	public void hideZombie() {
		zombie.setCullHint(CullHint.Always);
	}

	public Quad getRadar() {
		return radar;
	}

	public void setRadar(Quad radar) {
		this.radar = radar;
	}
	
	
	
	private Quad getRadarQuad(ColorRGBA color) {
		if(unusedRadarQuads.size() == 0) {
			// Create new
			Quad radarQuad = new Quad("hud", 4, 4);
			radarQuad.setRenderQueueMode(Renderer.QUEUE_ORTHO);
			
			radarQuad.setSolidColor(color);
			
			radarQuad.setLightCombineMode(Spatial.LightCombineMode.Off);
			radarQuad.updateRenderState();
			
			radarQuad.setCullHint(CullHint.Always);
			
			this.attachChild(radarQuad);
			
			unusedRadarQuads.push(radarQuad);
		}
		return unusedRadarQuads.pop();
	}
	
	
	public void updateRadar() {
		for(Quad q:radarQuads) {
			q.setCullHint(CullHint.Always);
			unusedRadarQuads.push(q);
		}
		radarQuads.clear();
		
		cameraDir = new Quaternion();
		Vector3f[] axis = new Vector3f[3];
		axis[0] = Game.getGame().getCamera().getLeft();
		axis[1] = Game.getGame().getCamera().getUp();
		axis[2] = Game.getGame().getCamera().getDirection();
		cameraDir.fromAxes(axis);
		
		cameraDir.inverseLocal();
		
		RotwGameState gameState = (RotwGameState)GameStateManager.getInstance().getChild("gameState");
		
		
		Vector<BaseAttacker> attackers = AttackerList.getAttackers();
		for(BaseAttacker att:attackers) {
			if(gameState.getPlayer().getLocalTranslation().distance(att.getLocalTranslation()) < 50) {
				drawRadarDot(att.getLocalTranslation(), ColorRGBA.green);
				
				
			}
		}
		
		if(gameState.getGameMode() instanceof DefendYourBase) {
			Flag base = (Flag)((DefendYourBase)gameState.getGameMode()).getBaseStation();
			drawRadarDot(base.getFlagPole().getWorldTranslation(), ColorRGBA.red);
		}
		
		Iterator<Person> persons = OpponentList.getInstance().getOpponents().values().iterator();
		while(persons.hasNext()) {
			Person p = persons.next();
			
			if(p == gameState.getPlayer()) continue;
			
			if(!gameState.useTeams() || gameState.getPlayer().getTeam() == p.getTeam()) {
				if(gameState.getPlayer().getLocalTranslation().distance(p.getLocalTranslation()) < 50) {
					drawRadarDot(p.getLocalTranslation(), ColorRGBA.yellow);
				}
			}
		}
		
		// Zombies
		if(gameState.getGameMode() instanceof CaptureTheZombie) {
			for(int i=0;i<2;i++) {
				if(gameState.getPlayer().getLocalTranslation().distance(((CaptureTheZombie)gameState.getGameMode()).getZombie(i).getLocalTranslation()) < 50) {
					drawRadarDot(((CaptureTheZombie)gameState.getGameMode()).getZombie(i).getLocalTranslation(), ColorRGBA.red);				
				}
			}
		}
	}
	
	private void drawRadarDot(Vector3f location, ColorRGBA color) {
		RotwGameState gameState = (RotwGameState)GameStateManager.getInstance().getChild("gameState");
		
		float xDistance = gameState.getPlayer().getLocalTranslation().x - location.x;
		float zDistance = gameState.getPlayer().getLocalTranslation().z - location.z;

		xDistance *= 128f/50.0f;
		zDistance *= 128f/50.0f;
		
		double distance = Math.sqrt(xDistance * xDistance + zDistance * zDistance);
		
		
		// In Circle
		if(distance < 64) {
			
			Vector3f loc = new Vector3f(xDistance,0,zDistance);
			cameraDir.multLocal(loc);
			
			
			Quad rq = getRadarQuad(color);
			rq.setCullHint(CullHint.Never);
			rq.setSolidColor(color);
			rq.setLocalTranslation(new Vector3f(
					Game.getGame().getDisplay().getWidth() - 64 + loc.x,
					Game.getGame().getDisplay().getHeight()-64 - loc.z,
					1));
			
			radarQuads.add(rq);
		}
	}
}
